home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / mcr12.c < prev    next >
C/C++ Source or Header  |  2000-04-08  |  13KB  |  520 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/mcr12.c
  4.  
  5.   Functions to emulate the video hardware of the MCR I and MCR II machines.
  6.  
  7.   Journey is an MCR/II game with a MCR/III sprite board so it has it's own
  8.   routines.
  9.  
  10. ***************************************************************************/
  11.  
  12. #include "driver.h"
  13. #include "machine/mcr.h"
  14. #include "vidhrdw/generic.h"
  15.  
  16.  
  17. #ifndef INCLUDE_DRAW_CORE
  18.  
  19. static UINT8 last_cocktail_flip;
  20. static UINT8 *spritebitmap;
  21. static UINT32 spritebitmap_width;
  22. static UINT32 spritebitmap_height;
  23.  
  24. static void render_one_sprite(int code, int sx, int sy, int hflip, int vflip);
  25. static void render_sprite_tile_8(struct osd_bitmap *bitmap, const UINT16 *pens, int sx, int sy);
  26. static void render_sprite_tile_16(struct osd_bitmap *bitmap, const UINT16 *pens, int sx, int sy);
  27.  
  28. INT8 mcr12_sprite_xoffs;
  29. INT8 mcr12_sprite_xoffs_flip;
  30.  
  31. static UINT8 xtiles, ytiles;
  32.  
  33.  
  34. /*************************************
  35.  *
  36.  *    Common video startup/shutdown
  37.  *
  38.  *************************************/
  39.  
  40. int mcr12_vh_start(void)
  41. {
  42.     const struct GfxElement *gfx = Machine->gfx[1];
  43.  
  44.     /* allocate a temporary bitmap for the sprite rendering */
  45.     spritebitmap_width = Machine->drv->screen_width + 2 * 32;
  46.     spritebitmap_height = Machine->drv->screen_height + 2 * 32;
  47.     spritebitmap = malloc(spritebitmap_width * spritebitmap_height);
  48.     if (!spritebitmap)
  49.         return 1;
  50.     memset(spritebitmap, 0, spritebitmap_width * spritebitmap_height);
  51.  
  52.     /* if we're swapped in X/Y, the sprite data will be swapped */
  53.     /* but that's not what we want, so we swap it back here */
  54.     if (gfx && (Machine->orientation & ORIENTATION_SWAP_XY))
  55.     {
  56.         UINT8 *base = gfx->gfxdata;
  57.         int c, x, y;
  58.         for (c = 0; c < gfx->total_elements; c++)
  59.         {
  60.             for (y = 0; y < gfx->height; y++)
  61.                 for (x = y; x < gfx->width; x++)
  62.                 {
  63.                     int temp = base[y * gfx->line_modulo + x];
  64.                     base[y * gfx->line_modulo + x] = base[x * gfx->line_modulo + y];
  65.                     base[x * gfx->line_modulo + y] = temp;
  66.                 }
  67.             base += gfx->char_modulo;
  68.         }
  69.     }
  70.  
  71.     /* compute tile counts */
  72.     xtiles = Machine->drv->screen_width / 16;
  73.     ytiles = Machine->drv->screen_height / 16;
  74.     last_cocktail_flip = 0;
  75.  
  76.     /* start up the generic system */
  77.     if (generic_vh_start())
  78.     {
  79.         free(spritebitmap);
  80.         spritebitmap = NULL;
  81.         return 1;
  82.     }
  83.     return 0;
  84. }
  85.  
  86.  
  87. void mcr12_vh_stop(void)
  88. {
  89.     generic_vh_stop();
  90.  
  91.     if (spritebitmap)
  92.         free(spritebitmap);
  93.     spritebitmap = NULL;
  94. }
  95.  
  96.  
  97.  
  98. /*************************************
  99.  *
  100.  *    MCR2 palette writes
  101.  *
  102.  *************************************/
  103.  
  104. WRITE_HANDLER( mcr2_paletteram_w )
  105. {
  106.     int r, g, b;
  107.  
  108.     paletteram[offset] = data;
  109.  
  110.     /* bit 2 of the red component is taken from bit 0 of the address */
  111.     r = ((offset & 1) << 2) + (data >> 6);
  112.     g = (data >> 0) & 7;
  113.     b = (data >> 3) & 7;
  114.  
  115.     /* up to 8 bits */
  116.     r = (r << 5) | (r << 2) | (r >> 1);
  117.     g = (g << 5) | (g << 2) | (g >> 1);
  118.     b = (b << 5) | (b << 2) | (b >> 1);
  119.  
  120.     palette_change_color(offset / 2, r, g, b);
  121. }
  122.  
  123.  
  124.  
  125. /*************************************
  126.  *
  127.  *    Videoram writes
  128.  *
  129.  *************************************/
  130.  
  131. WRITE_HANDLER( mcr1_videoram_w )
  132. {
  133.     if (videoram[offset] != data)
  134.     {
  135.         dirtybuffer[offset] = 1;
  136.         videoram[offset] = data;
  137.     }
  138. }
  139.  
  140.  
  141. WRITE_HANDLER( mcr2_videoram_w )
  142. {
  143.     if (videoram[offset] != data)
  144.     {
  145.         dirtybuffer[offset & ~1] = 1;
  146.         videoram[offset] = data;
  147.     }
  148. }
  149.  
  150.  
  151.  
  152. /*************************************
  153.  *
  154.  *    Background updates
  155.  *
  156.  *************************************/
  157.  
  158. static void mcr1_update_background(struct osd_bitmap *bitmap)
  159. {
  160.     int offs;
  161.  
  162.     /* for every character in the Video RAM, check if it has been modified */
  163.     /* since last time and update it accordingly. */
  164.     for (offs = videoram_size - 1; offs >= 0; offs--)
  165.     {
  166.         int dirty = dirtybuffer[offs];
  167.         if (dirty)
  168.         {
  169.             int mx = offs % 32;
  170.             int my = offs / 32;
  171.             int sx = 16 * mx;
  172.             int sy = 16 * my;
  173.  
  174.             int code = videoram[offs];
  175.  
  176.             /* adjust for cocktail mode */
  177.             if (mcr_cocktail_flip)
  178.             {
  179.                 sx = (xtiles - 1) * 16 - sx;
  180.                 sy = (ytiles - 1) * 16 - sy;
  181.             }
  182.  
  183.             /* draw the tile */
  184.             drawgfx(bitmap, Machine->gfx[0], code, 0, mcr_cocktail_flip, mcr_cocktail_flip,
  185.                     sx, sy, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  186.  
  187.             /* if there's live sprite data here, draw the sprite data */
  188.             if (dirty & 2)
  189.             {
  190.                 /* draw the sprite */
  191.                 if (bitmap->depth == 8)
  192.                     render_sprite_tile_8(bitmap, &Machine->pens[16], sx, sy);
  193.                 else
  194.                     render_sprite_tile_16(bitmap, &Machine->pens[16], sx, sy);
  195.             }
  196.  
  197.             /* shift off the low bit of the dirty buffer */
  198.             dirtybuffer[offs] = dirty >> 1;
  199.         }
  200.     }
  201. }
  202.  
  203.  
  204. static void mcr2_update_background(struct osd_bitmap *bitmap, int check_sprites)
  205. {
  206.     int offs;
  207.  
  208.     /* for every character in the Video RAM, check if it has been modified */
  209.     /* since last time and update it accordingly. */
  210.     for (offs = videoram_size - 2; offs >= 0; offs -= 2)
  211.     {
  212.         int dirty = dirtybuffer[offs];
  213.         if (dirty)
  214.         {
  215.             int mx = (offs / 2) % 32;
  216.             int my = (offs / 2) / 32;
  217.             int sx = 16 * mx;
  218.             int sy = 16 * my;
  219.  
  220.             int attr = videoram[offs + 1];
  221.             int code = videoram[offs] + 256 * (attr & 0x01);
  222.             int hflip = attr & 0x02;
  223.             int vflip = attr & 0x04;
  224.             int color = (attr & 0x18) >> 3;
  225.  
  226.             /* adjust for cocktail mode */
  227.             if (mcr_cocktail_flip)
  228.             {
  229.                 sx = (xtiles - 1) * 16 - sx;
  230.                 sy = (ytiles - 1) * 16 - sy;
  231.                 hflip = !hflip;
  232.                 vflip = !vflip;
  233.             }
  234.  
  235.             /* draw the tile */
  236.             drawgfx(bitmap, Machine->gfx[0], code, color, hflip, vflip,
  237.                     sx, sy, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  238.  
  239.             /* if there's live sprite data here, draw the sprite data */
  240.             if (check_sprites && (dirty & 2))
  241.             {
  242.                 color = (attr & 0xc0) >> 6;
  243.  
  244.                 /* draw the sprite */
  245.                 if (bitmap->depth == 8)
  246.                     render_sprite_tile_8(bitmap, &Machine->pens[color * 16], sx, sy);
  247.                 else
  248.                     render_sprite_tile_16(bitmap, &Machine->pens[color * 16], sx, sy);
  249.             }
  250.  
  251.             /* shift off the low bit of the dirty buffer */
  252.             dirtybuffer[offs] = dirty >> 1;
  253.         }
  254.     }
  255. }
  256.  
  257.  
  258.  
  259. /*************************************
  260.  *
  261.  *    Common sprite update
  262.  *
  263.  *************************************/
  264.  
  265. static void mcr12_update_sprites(int scale)
  266. {
  267.     int offs;
  268.  
  269.     /* render the sprites into the bitmap, ORing together */
  270.     for (offs = 0; offs < spriteram_size; offs += 4)
  271.     {
  272.         int code, x, y, sx, sy, xcount, ycount, xtile, ytile, hflip, vflip;
  273.  
  274.         /* skip if zero */
  275.         if (spriteram[offs] == 0)
  276.             continue;
  277.  
  278.         /* extract the bits of information */
  279.         code = spriteram[offs + 1] & 0x3f;
  280.         hflip = spriteram[offs + 1] & 0x40;
  281.         vflip = spriteram[offs + 1] & 0x80;
  282.         x = (spriteram[offs + 2] - 4) * 2;
  283.         y = (240 - spriteram[offs]) * 2;
  284.  
  285.         /* apply cocktail mode */
  286.         if (mcr_cocktail_flip)
  287.         {
  288.             hflip = !hflip;
  289.             vflip = !vflip;
  290.             x = 466 - x + mcr12_sprite_xoffs_flip;
  291.             y = 450 - y;
  292.         }
  293.         else
  294.             x += mcr12_sprite_xoffs;
  295.  
  296.         /* wrap and clip */
  297.         if (x > Machine->drv->visible_area.max_x)
  298.             x -= 512;
  299.         if (y > Machine->drv->visible_area.max_y)
  300.             y -= 512;
  301.         if (x <= -32 || y <= -32)
  302.             continue;
  303.  
  304.         /* draw the sprite into the sprite bitmap */
  305.         render_one_sprite(code, x + 32, y + 32, hflip, vflip);
  306.  
  307.         /* determine which tiles we will overdraw with this sprite */
  308.         sx = x / 16;
  309.         sy = y / 16;
  310.         xcount = (x & 15) ? 3 : 2;
  311.         ycount = (y & 15) ? 3 : 2;
  312.  
  313.         /* loop over dirty tiles and set the sprite bit */
  314.         for (ytile = sy; ytile < sy + ycount; ytile++)
  315.             for (xtile = sx; xtile < sx + xcount; xtile++)
  316.                 if (xtile >= 0 && xtile < xtiles && ytile >= 0 && ytile < ytiles)
  317.                 {
  318.                     int off;
  319.                     if (!mcr_cocktail_flip)
  320.                         off = 32 * ytile + xtile;
  321.                     else
  322.                         off = 32 * (ytiles - 1 - ytile) + (xtiles - 1 - xtile);
  323.                     dirtybuffer[off << scale] |= 2;
  324.                 }
  325.     }
  326. }
  327.  
  328.  
  329.  
  330. /*************************************
  331.  *
  332.  *    Main refresh routines
  333.  *
  334.  *************************************/
  335.  
  336. void mcr1_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  337. {
  338.     /* mark everything dirty on a full refresh or cocktail flip change */
  339.     if (palette_recalc() || full_refresh || last_cocktail_flip != mcr_cocktail_flip)
  340.         memset(dirtybuffer, 1, videoram_size);
  341.     last_cocktail_flip = mcr_cocktail_flip;
  342.  
  343.     /* update the sprites */
  344.     mcr12_update_sprites(0);
  345.  
  346.     /* redraw everything, merging the bitmaps */
  347.     mcr1_update_background(bitmap);
  348. }
  349.  
  350.  
  351. void mcr2_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  352. {
  353.     /* mark everything dirty on a full refresh or cocktail flip change */
  354.     if (palette_recalc() || full_refresh || last_cocktail_flip != mcr_cocktail_flip)
  355.         memset(dirtybuffer, 1, videoram_size);
  356.     last_cocktail_flip = mcr_cocktail_flip;
  357.  
  358.     /* update the sprites */
  359.     mcr12_update_sprites(1);
  360.  
  361.     /* redraw everything, merging the bitmaps */
  362.     mcr2_update_background(bitmap, 1);
  363. }
  364.  
  365.  
  366.  
  367. /*************************************
  368.  *
  369.  *    Journey-specific MCR2 redraw
  370.  *
  371.  *    Uses the MCR3 sprite drawing
  372.  *
  373.  *************************************/
  374.  
  375. extern void mcr3_update_sprites(struct osd_bitmap *bitmap, int color_mask, int code_xor, int dx, int dy);
  376.  
  377. void journey_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  378. {
  379.     /* mark everything dirty on a cocktail flip change */
  380.     if (palette_recalc() || last_cocktail_flip != mcr_cocktail_flip)
  381.         memset(dirtybuffer, 1, videoram_size);
  382.     last_cocktail_flip = mcr_cocktail_flip;
  383.  
  384.     /* redraw the background */
  385.     mcr2_update_background(tmpbitmap, 0);
  386.  
  387.     /* copy it to the destination */
  388.     copybitmap(bitmap, tmpbitmap, 0, 0, 0, 0, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  389.  
  390.     /* draw the sprites */
  391.     mcr3_update_sprites(bitmap, 0x03, 0, 0, 0);
  392. }
  393.  
  394.  
  395.  
  396. /*************************************
  397.  *
  398.  *        Sprite drawing
  399.  *
  400.  *************************************/
  401.  
  402. static void render_one_sprite(int code, int sx, int sy, int hflip, int vflip)
  403. {
  404.     const struct GfxElement *gfx = Machine->gfx[1];
  405.     UINT8 *src = gfx->gfxdata + gfx->char_modulo * code;
  406.     int y, x;
  407.  
  408.     /* adjust for vflip */
  409.     if (vflip)
  410.         src += 31 * gfx->line_modulo;
  411.  
  412.     /* loop over lines in the sprite */
  413.     for (y = 0; y < 32; y++, sy++)
  414.     {
  415.         UINT8 *dst = spritebitmap + spritebitmap_width * sy + sx;
  416.  
  417.         /* redraw the line */
  418.         if (!hflip)
  419.         {
  420.             for (x = 0; x < 32; x++)
  421.                 *dst++ |= *src++;
  422.         }
  423.         else
  424.         {
  425.             src += 32;
  426.             for (x = 0; x < 32; x++)
  427.                 *dst++ |= *--src;
  428.             src += 32;
  429.         }
  430.  
  431.         /* adjust for vflip */
  432.         if (vflip)
  433.             src -= 2 * gfx->line_modulo;
  434.     }
  435. }
  436.  
  437.  
  438.  
  439. /*************************************
  440.  *
  441.  *        Depth-specific refresh
  442.  *
  443.  *************************************/
  444.  
  445. #define ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, x, y, xadv)    \
  446.     if (orientation)                                                    \
  447.     {                                                                    \
  448.         int dy = bitmap->line[1] - bitmap->line[0];                        \
  449.         int tx = x, ty = y, temp;                                        \
  450.         if (orientation & ORIENTATION_SWAP_XY)                            \
  451.         {                                                                \
  452.             temp = tx; tx = ty; ty = temp;                                \
  453.             xadv = dy / (bitmap->depth / 8);                            \
  454.         }                                                                \
  455.         if (orientation & ORIENTATION_FLIP_X)                            \
  456.         {                                                                \
  457.             tx = bitmap->width - 1 - tx;                                \
  458.             if (!(orientation & ORIENTATION_SWAP_XY)) xadv = -xadv;        \
  459.         }                                                                \
  460.         if (orientation & ORIENTATION_FLIP_Y)                            \
  461.         {                                                                \
  462.             ty = bitmap->height - 1 - ty;                                \
  463.             if ((orientation & ORIENTATION_SWAP_XY)) xadv = -xadv;        \
  464.         }                                                                \
  465.         /* can't lookup line because it may be negative! */                \
  466.         dst = (TYPE *)(bitmap->line[0] + dy * ty) + tx;                    \
  467.     }
  468.  
  469. #define INCLUDE_DRAW_CORE
  470.  
  471. #define DRAW_FUNC render_sprite_tile_8
  472. #define TYPE UINT8
  473. #include "mcr12.c"
  474. #undef TYPE
  475. #undef DRAW_FUNC
  476.  
  477. #define DRAW_FUNC render_sprite_tile_16
  478. #define TYPE UINT16
  479. #include "mcr12.c"
  480. #undef TYPE
  481. #undef DRAW_FUNC
  482.  
  483.  
  484. #else
  485.  
  486.  
  487. /*************************************
  488.  *
  489.  *        Core refresh routine
  490.  *
  491.  *************************************/
  492.  
  493. void DRAW_FUNC(struct osd_bitmap *bitmap, const UINT16 *pens, int sx, int sy)
  494. {
  495.     int orientation = Machine->orientation;
  496.     int x, y;
  497.  
  498.     /* draw any dirty scanlines from the VRAM directly */
  499.     for (y = 0; y < 16; y++, sy++)
  500.     {
  501.         UINT8 *src = &spritebitmap[(sy + 32) * spritebitmap_width + (sx + 32)];
  502.         TYPE *dst = &((TYPE *)bitmap->line[sy])[sx];
  503.         int xadv = 1;
  504.  
  505.         /* adjust in case we're oddly oriented */
  506.         ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, sx, sy, xadv);
  507.  
  508.         /* redraw the sprite scanline, erasing as we go */
  509.         for (x = 0; x < 16; x++, dst += xadv)
  510.         {
  511.             int pixel = *src;
  512.             if (pixel & 7)
  513.                 *dst = pens[pixel];
  514.             *src++ = 0;
  515.         }
  516.     }
  517. }
  518.  
  519. #endif
  520.